package cn.tedu.project.oa.sys.user.service.impl;


import cn.tedu.project.oa.base.exception.ServiceException;
import cn.tedu.project.oa.base.response.StatusCode;
import cn.tedu.project.oa.base.response.StatusConstants;
import cn.tedu.project.oa.base.util.PasswordUtil;
import cn.tedu.project.oa.base.util.RedisUtil;
import cn.tedu.project.oa.base.util.TokenUtil;
import cn.tedu.project.oa.sys.role.mapper.RoleMapper;
import cn.tedu.project.oa.sys.role.pojo.vo.RoleVO;
import cn.tedu.project.oa.sys.user.mapper.UserMapper;
import cn.tedu.project.oa.sys.user.mapper.UserRoleMapper;
import cn.tedu.project.oa.sys.user.pojo.dto.*;
import cn.tedu.project.oa.sys.user.pojo.entity.User;
import cn.tedu.project.oa.sys.user.pojo.vo.LoginVO;
import cn.tedu.project.oa.sys.user.pojo.vo.UserVO;
import cn.tedu.project.oa.sys.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @Description: 用户业务实现类
 * @Author: Miles
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    private static final String DEFAULT_ROLE_NAME = "ROLE_USER";

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private TokenUtil tokenUtil;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    // 定义 Redis 中存储验证码的键前缀
    @Value("${captcha.redis.key.prefix}")
    private String captchaKeyPrefix;

    /**
     * 用户登录业务
     *
     * @param loginPara 登录参数
     * @return 登录结果
     */
    @Override
    public LoginVO login(LoginPara loginPara) {
        log.debug("登录业务参数:loginPara: {}", loginPara);

        log.debug("登录业务验证码关键字: {}", loginPara.getCaptchaKey());

        //获取验证码
        Object captcha = redisUtil.get(captchaKeyPrefix.concat(loginPara.getCaptchaKey()));
        log.debug("登录业务验证码: {}", captcha);

        LoginVO loginVO = new LoginVO(); // 初始化 loginVO
        UserVO userVO = userMapper.selectUserByUserName(loginPara.getUsername());
        if (userVO == null) {
            log.debug("登录业务该用户名不存在");
            throw new ServiceException(StatusCode.USERNAME_ERROR);
        }
        log.debug("登录用户的信息：{}", userVO);
        BeanUtils.copyProperties(userVO, loginVO);
        //密码是否正确
        if (!PasswordUtil.checkPassword(loginPara.getPassword(), userVO.getPassword())) {
            throw new ServiceException(StatusCode.PASSWORD_ERROR);
        }
        //验证码是否过期
        if (captcha == null) {
            log.debug("登录业务验证码已过期");
            throw new ServiceException(StatusCode.CODE_EXPIRED);
        }
        //验证码是否正确
        String captchaStr = captcha.toString();
        if (!captchaStr.equalsIgnoreCase(loginPara.getCode())) {
            throw new ServiceException(StatusCode.CODE_ERROR);
        }

        if (loginVO.getStatus() != StatusConstants.USER_ACTIVE.getCode() && loginVO.getStatus() != StatusConstants.USER_INIT.getCode()) {
            log.debug("该账号已被禁用");
            throw new ServiceException(StatusCode.USER_IS_BANNED);
        }

        log.debug("登录成功:loginVO: {}", loginVO);
        loginVO.setToken(tokenUtil.getToken(loginPara));

        return loginVO;
    }

    /**
     * 添加用户业务实现
     *
     * @param addUserPara 添加用户参数
     */
    @Transactional
    @Override
    public void addUser(AddUserPara addUserPara) {
        log.debug("添加用户业务参数:addUserPara: {}", addUserPara);
        //判断用户名是否存在
        if (userMapper.selectUserByUserName(addUserPara.getUsername()) != null) {
            log.debug("添加用户业务中该用户名已存在");
            throw new ServiceException(StatusCode.USERNAME_ALREADY_EXISTS);
        }
        User user = new User();
        BeanUtils.copyProperties(addUserPara, user);
        user.setPassword(PasswordUtil.hashPassword(user.getPassword()));
        user.setCreateTime(new Date());
        userMapper.insertUser(user);
        log.debug("添加用户成功:user: {}", user);
        // 新增用户的角色信息到用户角色关联表
        if (addUserPara.getRoles() != null && !addUserPara.getRoles().isEmpty()) {
            for (String roleName : addUserPara.getRoles()) {
                //传递过来的是角色名称,通过角色名称查询一个角色
                RoleVO role = roleMapper.selectRoleByName(roleName);
                UserVO userVO = userMapper.selectUserByUserName(user.getUsername());
                log.debug("新增用户角色表UserVO{}", userVO);
                userRoleMapper.insertUserRole(userVO.getId(), role.getId());
            }
        }
        //TODO 发送邮件通知管理员
    }

    /**
     * 编辑用户状态业务实现
     *
     * @param id     用户ID
     * @param status 状态
     */
    @Override
    public void editUserStatus(Long id, int status) {
        log.debug("编辑用户状态业务参数:id: {}, status: {}", id, status);
        UserVO userVO = userMapper.selectUserById(id);
        if (userVO == null) {
            throw new ServiceException(StatusCode.VALIDATE_ERROR);
        }
        //将该账号初始化
        if (userVO.getStatus() == StatusConstants.USER_INIT.getCode()) {
            //TODO 初始化账号，发送通知管理员
        }
        //判断状态是否合法
        if (status != StatusConstants.USER_ACTIVE.getCode() && status != StatusConstants.USER_INACTIVE.getCode()) {
            throw new ServiceException(StatusCode.VALIDATE_ERROR);
        }
        User user = new User();
        user.setId(id);
        user.setUpdateTime(new Date());
        user.setStatus(status);
        userMapper.updateUser(user);
    }

    /**
     * 查询用户业务实现
     *
     * @param userQueryPara 查询参数
     * @return 用户列表
     */
    @Override
    public List<UserVO> queryUser(UserQueryPara userQueryPara) {
        log.debug("查询用户业务参数:userQueryPara: {}", userQueryPara);
        List<UserVO> userVOList = userMapper.selectUserList(userQueryPara);
        return userVOList;
    }

    @Override
    public UserVO queryUserById(Long id) {
        UserVO userVO = userMapper.selectUserById(id);
        log.debug("根据id:{}，查询用户:{}", id, userVO);
        return userVO;
    }

    /**
     * 查询用户详情业务实现
     *
     * @param userEditPara 查询参数
     */
    @Override
    public void editUser(UserEditPara userEditPara) {
        log.debug("编辑用户业务参数:userEditPare: {}", userEditPara);
        User user = new User();
        BeanUtils.copyProperties(userEditPara, user);
        user.setUpdateTime(new Date());
        log.debug("编辑用户信息:user: {}", user);
        userMapper.updateUser(user);
    }

    /**
     * 修改密码业务实现
     *
     * @param passwordAlterPara
     */
    @Override
    public void editPassword(PasswordAlterPara passwordAlterPara) {
        log.debug("修改密码业务参数: {}", passwordAlterPara);

        // 检查新密码是否为空或者为空字符串
        if (passwordAlterPara.getNewPassword() == null || passwordAlterPara.getNewPassword().trim().isEmpty()) {
            throw new ServiceException(StatusCode.OPERATION_FAILED);
        }

        // 获取旧密码并检查是否存在
        String oldPassword = userMapper.selectPasswordById(passwordAlterPara.getId());
        if (oldPassword == null) {
            throw new ServiceException(StatusCode.VALIDATE_ERROR);
        }

        // 判断旧密码是否正确
        if (!PasswordUtil.checkPassword(passwordAlterPara.getOldPassword(), oldPassword)) {
            throw new ServiceException(StatusCode.OLD_PASSWORD_ERROR);
        }

        // 新密码不能与旧密码相同
        if (passwordAlterPara.getNewPassword().equals(passwordAlterPara.getOldPassword())) {
            throw new ServiceException(StatusCode.OPERATION_FAILED);
        }

        // 修改密码操作
        String hashedNewPassword = PasswordUtil.hashPassword(passwordAlterPara.getNewPassword());
        User user = new User();
        user.setId(passwordAlterPara.getId());
        user.setPassword(hashedNewPassword);
        user.setUpdateTime(new Date());

        userMapper.updateUser(user);
    }

    /**
     * 删除指定用户业务实现
     *
     * @param id 用户ID
     */
    @Override
    public void deleteUser(Long id) {
        log.debug("删除用户业务参数:id: {}", id);
        userMapper.deleteUserById(id);
        //TODO 删除相关用户内容(部门，职位，角色)
        //TODO 发送通知管理员
    }

    /**
     * 根据用户名查询用户和业务实现
     * @param username
     * @return
     */
    @Override
    public UserVO selectUserByName(String username) {
        UserVO user = userMapper.selectUserByUserName(username);
        List<RoleVO> roles = roleMapper.selectRoleByUserId(user.getId());
        //将角色添加经userVO中
        user.setRoles(roles);
        return user;
    }

    @Override
    public int count() {
        log.debug("查询用户数业务");

        int num = userMapper.count();

        return num;

    }

}
